import {
  Component,
  OnInit,
  ViewEncapsulation,
  ChangeDetectionStrategy,
  Input,
  Optional,
  OnDestroy,
  ChangeDetectorRef,
} from '@angular/core';
import { merge, Subject } from 'rxjs';
import { takeUntil, auditTime } from 'rxjs/operators';
import { LvSortDirection as SortDirection, LvPureSortDirection as PureSort } from '../core/api';
import { getSortHeaderNotContainedWithinSortError } from './sort-errors';
import { SortDirective } from './sort.directive';
import { SortConfig } from './interface';

@Component({
  selector: 'lv-sort-header',
  templateUrl: './sort-header.component.html',
  styles: [],
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    '[class.lv-sort]': 'true',
  },
})
export class SortHeaderComponent implements OnInit, SortConfig, OnDestroy {
  // 输入输出属性
  @Input('lvSortKey') key: string;
  @Input('lvDisableSortClear') disableSortClear; // 是否禁用清除排序
  @Input('lvDefaultSort') defaultSort: PureSort = 'asc';
  // @Input('sortDirection') direction: SortDirection; // 优先级大于sortConfig
  @Input('lvCustomSort') customSort: <T>(data: T[] | null) => T[] | null;

  // 外部可访问变量
  direction: SortDirection;

  // 内部变量
  _destroy$ = new Subject<void>();

  constructor(
    @Optional() private _sort: SortDirective,
    private cdf: ChangeDetectorRef,
  ) {
    if (!_sort) {
      throw getSortHeaderNotContainedWithinSortError();
    }
  }

  get _sortIcon(): string {
    return `lv-icon-sort${this.direction ? `-${this.direction}` : ''}`;
  }

  ngOnInit(): void {
    this._updateRender();
  }

  _changeSort(): void {
    this._sort.sort(this);
  }

  ngOnDestroy(): void {
    this._destroy$.next();
    this._destroy$.complete();
  }

  _updateDirective(): void {
    const source = this._sort;
    this.direction = source.key === this.key ? source.direction : '';
  }

  _updateRender(): void {
    merge(this._sort.lvSortChange, this._sort._stateChange)
      .pipe(auditTime(1), takeUntil(this._destroy$))
      .subscribe((): void => {
        this._updateDirective();
        this.cdf.markForCheck();
      });
  }
}
